package cn.demoncat.util.stock;

import cn.demoncat.util.exception.BizRuntimeException;
import cn.demoncat.util.lang.CollectionUtil;
import cn.demoncat.util.lang.JsonUtil;
import cn.demoncat.util.lang.LocalDateUtil;
import cn.demoncat.util.stock.constant.StockConstant;
import cn.demoncat.util.stock.entity.Market;
import cn.demoncat.util.web.HttpClientUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.HashMap;
import java.util.Map;

/**
 * 股票工具 - 聚合数据
 *
 * @author 延晓磊
 * @since 2023年10月19日
 */
@Component
public class JuheStockUtil implements StockUtil{

    // 服务Key
    @Value("${juhe.stock.key}")
    private String key;
    // 服务地址
    private static final String url = "http://web.juhe.cn/finance/stock/";

    /**
     * 查询市场行情
     *
     * @param bourse 交易所，编码非空时可以为空
     * @param code   编码
     *
     * @return
     */
    @Override
    public Market get(String bourse, String code) {
        // 参数处理
        Map<String,String> param = new HashMap<>();
        if (StringUtils.isBlank(code)) {
            // 指数
            if (StringUtils.isBlank(bourse)) {
                bourse = StockConstant.Bourse.SH;
            }
            param.put("type", StockConstant.Bourse.SH.equals(bourse) ? "0" : "1");
        }else{
            // 股票
            if (StringUtils.isBlank(bourse)) {
                // 识别交易所
                bourse = code.startsWith("6") ? StockConstant.Bourse.SH : StockConstant.Bourse.SZ;
            }
            param.put("gid", bourse + code);
        }
        // 发起请求
        JSONObject result = this.request("hs", param);
        // 整合结果
        Market market = new Market();
        JSONObject json;
        BigDecimal rate = new BigDecimal("1.1");
        if (StringUtils.isBlank(code)) {
            // 指数
            json = result;
            market.setBourse(bourse);
            market.setName(json.getString("name"));
            market.setRate(json.getBigDecimal("increPer"));
            market.setChange(json.getBigDecimal("increase"));
            market.setAmount(json.getBigDecimal("dealPri"));
            market.setVolume(json.getBigDecimal("dealNum"));
            market.setTime(LocalDateUtil.toLocalDateTime(json.getString("time")));
            // - 价格
            market.setPrice(new Market.Price());
            market.getPrice().setInit(json.getBigDecimal("yesPri"));
            market.getPrice().setOpen(json.getBigDecimal("openPri"));
            market.getPrice().setClose(json.getBigDecimal("nowpri"));
            market.getPrice().setHigh(json.getBigDecimal("highPri"));
            market.getPrice().setLow(json.getBigDecimal("lowpri"));
            market.getPrice().setMax(market.getPrice().getInit().multiply(rate).setScale(2, RoundingMode.FLOOR));
            market.getPrice().setMin(market.getPrice().getInit().divide(rate, 2, RoundingMode.FLOOR));
        }else{
            // 股票
            json = result.getJSONObject("data");
            market.setBourse(bourse);
            market.setCode(code);
            market.setName(json.getString("name"));
            market.setRate(json.getBigDecimal("increPer"));
            market.setChange(json.getBigDecimal("increase"));
            market.setAmount(json.getBigDecimal("traAmount"));
            market.setVolume(json.getBigDecimal("traNumber"));
            market.setTime(LocalDateUtil.toLocalDateTime(json.getString("date") + " " + json.getString("time")));
            // - 价格
            market.setPrice(new Market.Price());
            market.getPrice().setInit(json.getBigDecimal("yestodEndPri"));
            market.getPrice().setOpen(json.getBigDecimal("todayStartPri"));
            market.getPrice().setClose(json.getBigDecimal("nowPri"));
            market.getPrice().setHigh(json.getBigDecimal("todayMax"));
            market.getPrice().setLow(json.getBigDecimal("todayMin"));
            if (code.startsWith("3")) {
                // 创业板
                rate = new BigDecimal("1.2");
            }
            market.getPrice().setMax(market.getPrice().getInit().multiply(rate).setScale(2, RoundingMode.FLOOR));
            market.getPrice().setMin(market.getPrice().getInit().divide(rate, 2, RoundingMode.FLOOR));
            // - 买盘
            market.setBuy(CollectionUtil.toList(
                    Market.Step.build(json.getBigDecimal("buyOnePri"), json.getBigDecimal("buyOne")),
                    Market.Step.build(json.getBigDecimal("buyTwoPri"), json.getBigDecimal("buyTwo")),
                    Market.Step.build(json.getBigDecimal("buyThreePri"), json.getBigDecimal("buyThree")),
                    Market.Step.build(json.getBigDecimal("buyFourPri"), json.getBigDecimal("buyFour")),
                    Market.Step.build(json.getBigDecimal("buyFivePri"), json.getBigDecimal("buyFive"))
            ));
            // - 卖盘
            market.setSell(CollectionUtil.toList(
                    Market.Step.build(json.getBigDecimal("sellOnePri"), json.getBigDecimal("buyOne")),
                    Market.Step.build(json.getBigDecimal("sellTwoPri"), json.getBigDecimal("sellTwo")),
                    Market.Step.build(json.getBigDecimal("sellThreePri"), json.getBigDecimal("sellThree")),
                    Market.Step.build(json.getBigDecimal("sellFourPri"), json.getBigDecimal("buyFour")),
                    Market.Step.build(json.getBigDecimal("sellFivePri"), json.getBigDecimal("sellFive"))
            ));
            // - 图表
            json = result.getJSONObject("gopicture");
            market.setChart(new Market.Chart());
            market.getChart().setMin(json.getString("minurl"));
            market.getChart().setDay(json.getString("dayurl"));
            market.getChart().setWeek(json.getString("weekurl"));
            market.getChart().setMonth(json.getString("monthurl"));
        }
        return market;
    }


    /**
     * 发起请求
     *
     * @param path
     * @param param
     * @return
     */
    private JSONObject request(String path, Map<String,String> param){
        // 发起请求
        if (param == null) {
            param = new HashMap<>();
        }
        param.put("key", key);
        JSONObject json = JsonUtil.parseObject(HttpClientUtil.doGet(url + path, param));
        // 解析结果
        if (0 == json.getInteger("error_code")) {
            // 成功
            String result = json.getString("result");
            if (result.startsWith("{")) {
                return JSON.parseObject(result);
            }else{
                return JSON.parseArray(result).getJSONObject(0);
            }
        }else{
            // 失败
            throw new BizRuntimeException("请求聚合股票行情失败：" + json.getString("reason"));
        }
    }

}
